import { NavBar, PickerView, Toast } from 'antd-mobile'
import React, { Component , createRef } from 'react'
import SearchBar from '../../components/SearchBar'
import HouseItem from '../../components/HouseLtem/index'
import styles from './index.module.scss'
import { getCurrentCity } from '../../utils/baiduMap'
// import PickerViewExample from '../../demo/PickerViewExample'
import { getHousesCondition, getHousesByParams } from '../../api'
import { AutoSizer, List, WindowScroller, InfiniteLoader } from 'react-virtualized'

export default class ListFound extends Component {
  state = {
    cityName: '',
    cityArea: '',
    filterTabs: [
      { id: 1, text: '区域', cols: 3, openType: 'area' },
      { id: 2, text: '方式', cols: 1, openType: 'rent' },
      { id: 3, text: '租金', cols: 1, openType: 'price' },
      { id: 4, text: '筛选', cols: 0, openType: 'more' },
    ],
    // 选中状态的索引值
    activeIndex: -1,
    filterCondition: {
      area: [],
      rent: [],
      price: [],
      more: [],
    },
    filterData: {},
    maskShow: false,
    moreData: [],
    count: 0,
    list: [],
  }
  // 请求参数变量
  params = {}
  async componentDidMount() {
    // 获取当前定位城市
    const { label: cityName, value: cityArea } = await getCurrentCity()
    // 获取房屋查询条件
    const res = await getHousesCondition(cityArea)
    // 解构出查询条件数据
    const { area, subway, rentType, price, roomType, oriented, floor, characteristic } = res.data.body
    // 处理成功项目页面中需要的数据结构
    const filterCondition = {}
    // 条件1：区域和地铁
    filterCondition.area = [area, subway]
    // 条件2：租房方式
    filterCondition.rent = rentType
    // 条件3：租金
    filterCondition.price = price
    // 条件4：更多
    filterCondition.more = [
      { title: '户型', data: roomType },
      { title: '朝向', data: oriented },
      { title: '楼层', data: floor },
      { title: '房屋亮点', data: characteristic },
    ]
    // 更新状态
    this.setState({ cityName, cityArea, filterCondition })
    this.getHousesData()

    // 给浏览器绑定一个滚动事件
    window.addEventListener('scroll',this.windowScrollHandle)
  }
  // 创建 ref，用于查找到 DOM 元素
  tabsRef = createRef()
  windowScrollHandle = () => {
    // 获取DOM元素
    const tabsDom = this.tabsRef.current
    // 获取元素的相对于视口的 top 位置。
    const { top } = tabsDom.parentNode.getBoundingClientRect()
    console.log(top)
    if(top <= 0){
      tabsDom.classList.add(styles.filter_tabs_fixed)
    }else{
      tabsDom.classList.remove(styles.filter_tabs_fixed)
    }
  };
  // 因为其他页面不需要吸顶功能，所以需要把滚动事件移除掉
  componentWillUnmount(){
    window.removeEventListener('scroll',this.windowScrollHandle)
  }
  onChange = (value) => {
    // console.log(value)
    // 获取当前打开的到底是哪个选项卡
    const { filterTabs, activeIndex, filterData } = this.state
    const { openType } = filterTabs[activeIndex]
    // 把当前打开选项卡的 PickerView 数据存放起来
    filterData[openType] = value
    this.setState({ filterData })
    this.getParams(openType, value)
  }
  getParams = (openType, value) => {
    // 为请求的接口准备对应的请求参数
    // 难点:处理第一个 PickView 的值
    if (openType === 'area') {
      // 因为区域和地铁，只能选择其一，所以先把旧的地铁和区域都删除掉
      delete this.params.area
      delete this.params.subway
      // 在添加区域或地铁的请求参数，
      //   键：第一个 PickView 的数组的第一项为请求的键名称
      //   值：如果 PickView 数组的第三个值为 null，我们就使用第二个值，否则才使用第三个值
      const key = value[0]
      const val = value[2] === 'null' ? value[1] : value[2]
      this.params[key] = val
    } else if (openType === 'rent') {
      this.params.rentType = value[0]
    } else if (openType === 'price') {
      this.params.price = value[0]
    } else if (openType === 'more') {
      this.params.more = value
    }
    // 如果是 null 值就不需要发送了这些参数
    for (const key in this.params) {
      this.params[key] === 'null' && delete this.params[key]
    }
    // 添加城市 id 限制，否则如果没选择条件的时候，返回的是全国的房源信息
    this.params.cityId = this.state.cityArea
    this.params.start = 1
    this.params.end = 20
    console.log('用于发送请求的参数', this.params)
  }
  moreClick = () => {
    // 处理更多筛选的请求参数
    const value = this.state.moreData.join(',')
    this.getParams('more', value)
    this.getHousesData()
  }
  // 获取房源数据
  getHousesData = async () => {
    // 移除类名让页面能滚动
    document.body.classList.remove('ovh')
    // 参数准备完毕后，就发送请求获取房源信息
    this.setState({ activeIndex: -1, maskShow: false })
    this.getParams()
    const res = await getHousesByParams(this.params)
    // console.log(res)
    // count 代表一共有多少套房源，list 就是房源列表数据
    const { count, list } = res.data.body
    this.setState({ count, list })
    // 提示多少套房源
    Toast.info(`共找到 ${this.state.count} 套房源`, 1)
  }
  hideMask = () => {
    this.setState({ maskShow: false, activeIndex: -1 })
    document.body.classList.remove('ovh')
  }
  renderPickerFilter = () => {
    // 根据 activeIndex 索引找到当前 openType 打开方式 和 cols列数
    const { filterTabs, filterCondition, activeIndex, filterData } = this.state
    const { openType, cols } = filterTabs[activeIndex]
    return (
      <div className={styles.filter_content}>
        <div className={styles.filter_content_body}>
          {/* 前 3 个为 PickerView 展示，根据 openType 展示不同的数据  */}
          <PickerView value={filterData[openType]} onChange={this.onChange} data={filterCondition[openType]} cols={cols} />
        </div>
        <div className={styles.filter_content_footer}>
          <span onClick={this.hideMask}>取消</span>
          <span onClick={this.getHousesData}>确定</span>
        </div>
      </div>
    )
  }
  renderMoreFilter = () => {
    const { more } = this.state.filterCondition
    const { moreData } = this.state
    return (
      <div className={styles.more}>
        <div className={styles.more_content}>
          {more.map((item) => (
            <div key={item.title} className={styles.more_item}>
              <div className={styles.more_title}>{item.title}</div>
              <div className={styles.more_body}>
                {item.data.map((item2) => (
                  <span
                    // 通过 includes 检查当前的值是否在数组中，如果存在就添加选中状态
                    className={moreData.includes(item2.value) ? styles.active : ''}
                    key={item2.value}
                    onClick={() => {
                      // 查找当前点击的元素是否已经在数组中
                      const index = moreData.findIndex((item3) => item3 === item2.value)
                      // 如果不在数组中就添加进去
                      if (index === -1) {
                        moreData.push(item2.value)
                      }
                      // 如果已经在数组则删除掉
                      else {
                        moreData.splice(index, 1)
                      }
                      // 更新状态
                      this.setState({ moreData })
                    }}
                  >
                    {item2.label}
                  </span>
                ))}
              </div>
            </div>
          ))}
        </div>
        <div className={styles.filter_content_footer}>
          <span
            onClick={() => {
              this.setState({ moreData: [] })
            }}
          >
            清除
          </span>
          <span onClick={this.moreClick}>确定</span>
        </div>
      </div>
    )
  }
  rowRenderer = ({ index, key, style }) => {
    const item = this.state.list[index]
    // 如果有数据就渲染 HouseItem
    if (item) {
      return (
        <div key={key} style={style}>
          <HouseItem {...item}></HouseItem>
        </div>
      )
    }
    // 没有数据展示占位盒子
    else {
      return (
        <div key={key} style={style}>
          <div className={styles.load_house}></div>
        </div>
      )
    }
  }
  // 负责跟踪每一行的加载状态。
  isRowLoaded = ({ index }) => {
    return !!this.state.list[index];
  }
  // 当加载更多行时调用的回调，返回值必须是 Promise 对象。
  loadMoreRows = ({ startIndex, stopIndex }) => {
    return new Promise(async (resolve)=>{
      // 获取请求参数
      this.getParams()
      // 处理分页参数
      this.params.start = startIndex
      this.params.end = stopIndex
      // 根据分页参数发起请求
      const res = await getHousesByParams(this.params)
      // 这里是把新旧的两个数组合并起来
      this.setState({ list : [...this.state.list,...res.data.body.list] })
      resolve()
    })
  }
  renderFilterTabs = () => {
    const {  filterTabs , activeIndex, filterData, moreData } = this.state;
    return <div ref={this.tabsRef} className={styles.filter_tabs}>
      {filterTabs.map((item, index) => {
        // 当前遍历的元素是否需要选中
        let isSelected = false
        // 提取出当前打开的类型
        const { openType } = item
        // 根据类型提出出选中的值
        const data = filterData[openType] || []
        // 根据打开类型判断 area 是否有 3 级联动
        if( openType === 'area' && data.length === 3 ){
          isSelected = true
        }
        // 如果是租房方式或者租金，则判断值是否不为 'null' 或 undefined
        else if ( ['rent','price'].includes(openType) && !['null', undefined].includes(data[0]) ){
          isSelected = true
        }
        // 如果是更多筛选，判断 moreData 数组是否有长度即可
        else if (openType === 'more' && moreData.length){
          isSelected = true
        }
        
        return (
          <span
            className={[
              styles.filter_item, 
              activeIndex === index ? styles.active : '',
              isSelected ? styles.selected : '',
            ].join(' ')}
            key={item.id}
            onClick={() => {
              // 给 body 添加 ovh 类名禁止页面滚动
              document.body.classList.add('ovh')
              this.setState({ activeIndex: index, maskShow: true })
            }}
          >
            <span>{item.text}</span>
            <i className="iconfont icon-arrow"></i>
          </span>
        )
      })}
    </div>
  };
  render() {
    const { count, cityName,  activeIndex,  maskShow } = this.state
    return (
      <div className={styles.list}>
        {/* 1.0 头部搜索框 */}
        <NavBar
          mode="light"
          icon={<i className="iconfont icon-back" />}
          onLeftClick={() => {
            this.props.history.goBack()
          }}
        >
          <SearchBar cityName={cityName} />
        </NavBar>
        {/* 2.0 筛选分区 - 难 */}
        <div className={styles.filter}>
          {/* 筛选分区的遮罩层 */}
          <div
            style={activeIndex === 3 ? { zIndex: 3 } : { }} 
            onClick={this.hideMask} 
            className={[styles.mask, maskShow ? styles.mask_show : ''].join(' ')}
          ></div>
          {/* 2.1 筛选分区的 tabs 部分 */}
          {this.renderFilterTabs()}
          {/* 2.2 筛选分区的 内部部分 */}
          {activeIndex === 0 || activeIndex === 1 || activeIndex === 2 ? this.renderPickerFilter() : null}
          {activeIndex === 3 && this.renderMoreFilter()}
        </div>
        {/* 3.0 房源虚拟化列表 */}
        <div className={styles.list_main}>
          <InfiniteLoader
            isRowLoaded={this.isRowLoaded}
            loadMoreRows={this.loadMoreRows}
            rowCount={count}
            minimumBatchSize={10}
          >
            {({ onRowsRendered, registerChild }) => (
              <AutoSizer>
                {({ width }) => (
                <WindowScroller>
                  {({height, isScrolling, onChildScroll, scrollTop})=>(
                    <>
                      <List 
                        onRowsRendered={onRowsRendered}
                        ref={registerChild}
                        autoHeight
                        width={width} 
                        height={height} 
                        isScrolling={isScrolling} 
                        onScroll={onChildScroll} 
                        scrollTop={scrollTop}
                        rowCount={count} 
                        rowHeight={102} 
                        rowRenderer={this.rowRenderer} 
                      />
                      {/* 占位用的底部元素，防止底部被 tabBar 遮挡 */}
                      <div className={styles.list_bottom}></div>
                    </>
                  )}
                </WindowScroller>
              )}
              </AutoSizer>
            )}
          </InfiniteLoader>
        </div>
      </div>
    )
  }
}
